#!/usr/bin/perl -w
package OrangePl;

# Moduł wysyłający SMS-y na wszystkie polskie sieci przez bramkę
# www.orange.pl, portal "mbox" (tj. z koniecznością logowania).
# https://www.orange.pl/portal/map/map
# Napisany w Perlu. 
# Wymaga: perl + LWP + SSL (RPM-y dla RedHat: perl-libwww, perl-crypt-SSLeay).
#
# (c) 2003 Jacek Fiok <jfiok..jfiok.org>; http://sms.jfiok.org
# (c) 2008 Dawid Cieszyński <cieszak..cieszak.eu>; http://cieszak.eu
# wysyła wiadomości: do 640 znaków; wszystkie polskie sieci.
#
# Podziękowania dla:
# - Spley <spley..home.pl>
# - Maciej Krzyzanowski <spider..popnet.pl>
#
# Przerobka skryptu Ideii, po przemianowaniu sieci na Orange:
# - Rafal 'RaV.' Matczak <rafal.matczak.orangutan.poczta.finemedia.pl>


#class OrangePl
#{
#	$verbose
#		processing verbose level
#		possible level values:
#		0 - minimal
#		1 - information
#		2 - debug
#
#	$res
#		Result of request
#	new()
#		create new instance
#	debug($text)
#		show debug information if $verbose>1
#	notice($text)
#		show debug information if $verbose>0
#	login($username, $password)
#		login
#	sms_left
#		reading number of sms left
#	send_sms($number, $content)
#		send sms
#	_request_account()
#		request account page (for read sms left)
#}

use strict;

#wymagania: perl + LWP (perl-libwww)
use HTTP::Request::Common;
use HTTP::Cookies;
use LWP::UserAgent;
use Crypt::SSLeay;

#Sub: new
#	Constructor of SMSOrange class
sub new {
	my ($class) = @_;

	my $self = {
		_verbose    => 0,
		_ua         => new LWP::UserAgent,
		_cookie_jar => new HTTP::Cookies,

		_res      => undef,
		_username => undef,
		_password => undef,

		_loggedin => undef
	};

	#creating user agent
	$self->{_ua}->timeout(30);
	$self->{_ua}->agent("Mozilla/5.0 (Windows NT 6.1; WOW64; rv:14.0) Gecko/20100101 Firefox/14.0.1");
	$self->{_ua}->env_proxy();
	$self->{_ua}->cookie_jar( $self->{_cookie_jar} );

	bless $self, $class;
	return $self;
}

#Sub: login
#	Login to orange.pl
#
#	Parameters: username, password
sub login {
	my $self = shift;
	
	$self->{_username} = shift;
	$self->{_password} = shift;

	$self->debug( 'logowanie jako ' . $self->{_username} . ':' . $self->{_password} );
	$self->notice( 'Konto: ' . $self->{_username});
	push @{ $self->{_ua}->requests_redirectable }, 'POST';

	#getting start page
	$self->{_res} = $self->{_ua}->request( GET "https://www.orange.pl/zaloguj.phtml" );
	
	
	$self->write_file( "loginpage.html", $self->{_res}->content );
	if ( !( $self->{_res}->is_success ) ) {
		$self->notice("Blad przy otwieraniu formularza logowania");
		return 0;
	}

	#sending login form
	my $par1 = 'https://www.orange.pl/zaloguj.phtml?_DARGS=/ocp/gear/infoportal/portlets/login/login-box.jsp';

	$self->debug( "Logging in: " . $par1 );
	my $req = POST $par1,
	  [
		"_dyncharset"																	=>	"UTF-8",
		"_dynSessConf"																	=>	"-7322242883615328119",
		"/tp/core/profile/login/ProfileLoginFormHandler.loginErrorURL"					=>	"https://www.orange.pl/zaloguj.phtml",
		"_D:/tp/core/profile/login/ProfileLoginFormHandler.loginErrorURL"				=>	"",
		"/tp/core/profile/login/ProfileLoginFormHandler.loginSuccessURL"				=>	"",
		"_D:/tp/core/profile/login/ProfileLoginFormHandler.loginSuccessURL"				=>	"",
		"/tp/core/profile/login/ProfileLoginFormHandler.firstEnter"						=>	"true",
		"_D:/tp/core/profile/login/ProfileLoginFormHandler.firstEnter"					=>	"",
		"/tp/core/profile/login/ProfileLoginFormHandler.value.login"					=>	$self->{_username},
		"_D:/tp/core/profile/login/ProfileLoginFormHandler.value.login"					=>	"",
		"/tp/core/profile/login/ProfileLoginFormHandler.value.password"					=>	$self->{_password},
		"_D:/tp/core/profile/login/ProfileLoginFormHandler.value.password"				=>	"",
		"/tp/core/profile/login/ProfileLoginFormHandler.rememberMe"						=>	"false",
		"_D:/tp/core/profile/login/ProfileLoginFormHandler.rememberMe"					=>	"",
		"/tp/core/profile/login/ProfileLoginFormHandler.login"						=>	"Zaloguj się",
		"_D:/tp/core/profile/login/ProfileLoginFormHandler.login"						=>	"",
		"_DARGS" 																		=> 	"/ocp/gear/infoportal/portlets/login/login-box.jsp"
	  ];
	  
	$req->referer("https://www.orange.pl/zaloguj.phtml");
	$self->{_res} = $self->{_ua}->request($req);
	$self->write_file( "afterlogin.html", $self->{_res}->content );

	if ( $self->{_res}->content =~ /login-error msg err err-met/ ) {
		#<p class="login-error msg err err-met"> Podałeś niepoprawny login lub hasło. Spróbuj ponownie. </p>
		$self->notice("Blad przy logowaniu - bledny login lub haslo");
		return 0;
	}
	elsif ( $self->{_res}->content =~ /login-box__title/ ) {
		$self->notice("Blad przy logowaniu - nieprawidlowe haslo?");
		return 0;
	}
	$self->debug("Zalogowany");
	$self->{_loggedin} = 1;

	1;
}

#Sub: _request_account
#	Request account page (used for read sms left)
sub _request_account {
	my $self = shift;

	if ( !$self->{_loggedin} ) {
		$self->debug("You aren't logged in.");
	}

	my $req = GET 'http://www.orange.pl/portal/map/map/message_box?mbox_view=newsms&mbox_edit=new';
	$self->{_res} = $self->{_ua}->request($req);
}

#Sub: sms_left
#	Read number of sms's left on current account
sub sms_left {
	my $self = shift;

	if ( !$self->{_loggedin} ) {
		$self->debug("You aren't logged in.");
	}

	if ( $self->{_res}->content !~ /skrzynka MMS/ ) { _request_account($self); }
	my $accountpage = $self->{_res}->content;
	$self->write_file( "account.html", $accountpage );

	my $left_sms = -1;

	if ($accountpage =~ /<span class=\"label\">bezp.*?atne.*?:<\/span>.*?<span class=\"value\">([0-9]+).*?<\/span>.*?<span class=\"label\">z doładowa.*?:<\/span>.*?<span class=\"value\">([0-9]+)<\/span>/sm) {
		$left_sms = eval ($1) + eval ($2);
	} elsif ($accountpage =~ /<span class=\"label\">bezp.*?atne.*?:<\/span>.*?<span class=\"value\">([0-9]+)<\/span>/sm) {
		$left_sms = eval ($1);
	}

	$self->debug("Zostalo smsow: $left_sms");
	return $left_sms;
}

#Sub: send_sms
#	Sends sms by mBox
#	Parameters: number, message
sub send_sms {
	my $self = shift;

	if ( !$self->{_loggedin} ) {
		$self->debug("You aren't logged in.");
	}

	my $number = shift;
	$number =~ s/^\+48//;
	$number =~ s/^0048//;
	my $content = shift;
	$self->notice("SMS na numer $number");

	my $smsleft_before = $self->sms_left();


	#opening smssend form
	$self->{_res} = $self->{_ua}->request( GET 'https://www.orange.pl/portal/map/map/message_box?mbox_view=newsms&mbox_edit=new' );
	if ( !( $self->{_res}->is_success ) ) {
		$self->notice("Blad przy otwarciu formularza");
		return 0;
	}

	$self->write_file( "smsform.html", $self->{_res}->content );

	$self->notice("Pobieram token");
	my $token;
	if ($self->{_res}->content =~ /<input name="\/amg\/ptk\/map\/messagebox\/formhandlers\/MessageFormHandler.token" value="([a-zA-Z0-9]{1,15})" type="hidden"\/>/sm) { $token=$1; };
	if (!$token) { $self->error ("Token nie został pobrany prawidłowo",1);}
	$self->notice("Token " . $token);

	my $sss;
	if ($self->{_res}->content =~ /<input name="_dynSessConf" value="([^"]*)" type="hidden"\/>/sm) { $sss=$1; };
	if (!$sss) { $self->error ("ses nie został pobrany prawidłowo",1);}
	$self->notice("sess " . $sss);

	#sending sms
	my $req = POST 'https://www.orange.pl/portal/map/map/message_box?_DARGS=/gear/mapmessagebox/smsform.jsp',
		[
			'_dyncharset' => "UTF-8",
			"_dynSessConf"																	=>	$sss,
			'/amg/ptk/map/messagebox/formhandlers/MessageFormHandler.type' => "sms",
			'_D:/amg/ptk/map/messagebox/formhandlers/MessageFormHandler.type' => "",
			'/amg/ptk/map/messagebox/formhandlers/MessageFormHandler.errorURL' => '/portal/map/map/message_box?mbox_view=newsms',
			'_D:/amg/ptk/map/messagebox/formhandlers/MessageFormHandler.errorURL'  => "",
			'/amg/ptk/map/messagebox/formhandlers/MessageFormHandler.successURL' => '/portal/map/map/message_box?mbox_view=sentmessageslist',
			'_D:/amg/ptk/map/messagebox/formhandlers/MessageFormHandler.successURL' => "",
			'/amg/ptk/map/messagebox/formhandlers/MessageFormHandler.to' => $number,
			'_D:/amg/ptk/map/messagebox/formhandlers/MessageFormHandler.to' => "",
			'_D:/amg/ptk/map/messagebox/formhandlers/MessageFormHandler.body' => "",
			'/amg/ptk/map/messagebox/formhandlers/MessageFormHandler.body' => $content,
			'/amg/ptk/map/messagebox/formhandlers/MessageFormHandler.token' => $token,
			'_D:/amg/ptk/map/messagebox/formhandlers/MessageFormHandler.token' => '',
			'enabled' => "false",
#			'counter' => (640 - length($content)),
			'/amg/ptk/map/messagebox/formhandlers/MessageFormHandler.create.x' => 43,
			'/amg/ptk/map/messagebox/formhandlers/MessageFormHandler.create.y' => 8,
			'_D:/amg/ptk/map/messagebox/formhandlers/MessageFormHandler.create' => "",
			'_DARGS' => '/gear/mapmessagebox/smsform.jsp'
	  ];
	$req->referer('https://www.orange.pl/portal/map/map/message_box?mbox_view=newsms&mbox_edit=new');
	$self->debug("wysylanie smsa");

	$self->{_res} = $self->{_ua}->request($req);
	if ( !( $self->{_res}->is_success ) ) {
		$self->notice("Blad przy ostatecznym wysylaniu SMS");
		return 0;
	}

	$self->write_file( "smsformaftersend.html", $self->{_res}->content );

	my $smsleft_after = $self->sms_left();

	if ( $smsleft_after == -1 ) {
		$self->debug("Nie moge odczytac ilosci dostepnych SMSow");
	}
	else {
		if ( $smsleft_before > $smsleft_after ) {
			$self->debug( "Wszystko OK; pozostaly limit wiadomosci: " . $smsleft_after );
		}
		else {
			$self->debug( "Wiadomosc wyslana, ale STATUS NIEZNANY (pozostaly limit: " . $smsleft_after . ")." );
		}
		1;
	}
}

sub set_verbose {
	my ( $self, $verbose ) = @_;
	$self->{_verbose} = $verbose if defined($verbose);
	return $self->{_verbose};
}

#### DEBUG FUNCTIONS ####

#Sub: notice
#	Shows notice info if $verbose>0, else do nothing
sub notice {
	my $self = shift;
	if ( $self->{_verbose} > 0 ) {
		print "[N: ", shift, "]\n";
	} 
}

#Sub: debug
#	Shows debug info if $verbose>1, else do nothing
sub debug {
	my $self = shift;

	if ( $self->{_verbose} > 1 ) {
		print "[D: ", shift, "]\n";
	}
}

sub error {
	my $self = shift;

	if ( $self->{_verbose} > 1 ) {
		print "[E: ", shift, "]\n";
	}
}

#Sub: write_file
#   Write data to file if $verbose > 2, else do nothing
sub write_file {
	my $self = shift;
 
	if ( $self->{_verbose} > 2 ) {
		my ( $f, @data ) = @_;
		@data = () unless @data;
		mkdir("../cgi-log/");
		mkdir("../cgi-log/". $self->{_username}."/");
		$self->debug("../cgi-log/". $self->{_username}."/");
		$self->debug(get_timestamp());
		my $fn="../cgi-log/". $self->{_username} . "/" . $self->{_username}."_".get_timestamp()."$f";
		$self->debug($fn);
		open F, ">$fn" or $self->debug("Can't open $fn : $!");
		print F @data;
		close F;
	}
}

sub get_timestamp {
   my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime(time);
   if ($mon < 10) { $mon = "0$mon"; }
   if ($hour < 10) { $hour = "0$hour"; }
   if ($min < 10) { $min = "0$min"; }
   if ($sec < 10) { $sec = "0$sec"; }
   $year=$year+1900;

   return $year . '_' . $mon . '_' . $mday . '__' . $hour . '_' . $min . '_' . $sec;
}

#sample
# my $sms = new OrangePl();
# $sms->set_verbose(4);
# $sms->login( $ARGV[2], $ARGV[3] );
# print $ARGV[2]." ".$sms->sms_left . "\n" if $sms->sms_left < 9;
# $sms->send_sms( $ARGV[0], $ARGV[1] );


1;

